﻿using System.Windows;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using OpenCvSharp.WpfExtensions;
using VideoRecorder.Util;
using MessageBox = System.Windows.MessageBox;
using Window = HandyControl.Controls.Window;

namespace VideoRecorder;

public sealed partial class MainWindow : Window {
    private const string TAG = "[MainWindow]";

    private readonly MainWindowVM _vm = new();
    private readonly TimeLogger _log = new();

    public MainWindow() {
        DataContext = _vm;
        InitializeComponent();

        _vm.Camera.ReceivedFrame += CaptureOnNewFrame;
        _vm.ScreenCapture.CapturedFrame += ScreenCaptureOnCapturedFrame;
    }


    private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) {
        _vm.SelectedCamera = _vm.Devices.FirstOrDefault();
    }

    private void OpenCamera(object sender, RoutedEventArgs e) {
        if (_vm.IsRunning) return;

        if (_vm.IsScreenCapture) {
            _vm.StartScreenCapture();
        } else {
            if (_vm.SelectedCamera == null) {
                MessageBox.Show("请选择摄像头");
                return;
            }

            _vm.OpenCamera();
        }
    }

    private void CloseCamera(object sender, RoutedEventArgs e) {
        if (_vm.IsScreenCapture) {
            _vm.StopScreenCapture();
        } else {
            _vm.CloseCamera();
        }

        Dispatcher.Invoke(() => CameraTarget.Source = null);
    }

    private void ScreenCaptureOnCapturedFrame(Bitmap frame) {
        _log.Log("screen-new-frame");
        var mat = frame.ToMat();

        if (_vm.IsRecording) {
            _vm.Recorder.AddFrame(mat);
        }

        Dispatcher.Invoke(() => {
            if (!mat.IsDisposed) {
                CameraTarget.Source = mat.ToWriteableBitmap();
            }
        });
    }

    private void CaptureOnNewFrame(Mat mat) {
        _log.Log("new-frame");
        if (_vm.IsRecording) {
            _vm.Recorder.AddFrame(mat);
        }

        Dispatcher.Invoke(() => {
            if (!mat.IsDisposed) {
                CameraTarget.Source = mat.ToWriteableBitmap();
            }
        });
    }

    private void StartRecord(object sender, RoutedEventArgs e) => _vm.StartRecord();

    private void StopRecord(object sender, RoutedEventArgs e) => _vm.StopRecord();
}
